//
// Created on 2025/10/15.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef MSLITEVIDEOENHANCE_VIDEO_PROCESSOR_H
#define MSLITEVIDEOENHANCE_VIDEO_PROCESSOR_H

#include <cmath>
#include <iostream>
#include <string>
#include <vector>

// FFmpeg头文件
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>

#include <fftw3.h>
}


class VideoProcessor {
public:
    std::vector<float> read_wav_file(const std::string &filename, int &out_sample_rate) {
        AVFormatContext *format_ctx = nullptr;
        AVCodecContext *codec_ctx = nullptr;
        std::vector<float> audio_data;

        avformat_network_init();

        // 打开音频文件
        if (avformat_open_input(&format_ctx, filename.c_str(), nullptr, nullptr) != 0) {
            throw std::runtime_error("无法打开音频文件: " + filename);
        }

        if (avformat_find_stream_info(format_ctx, nullptr) < 0) {
            avformat_close_input(&format_ctx);
            throw std::runtime_error("无法获取流信息");
        }

        // 查找音频流
        int audio_stream_index = -1;
        for (unsigned int i = 0; i < format_ctx->nb_streams; i++) {
            if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
                audio_stream_index = i;
                break;
            }
        }

        if (audio_stream_index == -1) {
            avformat_close_input(&format_ctx);
            throw std::runtime_error("未找到音频流");
        }

        // 获取解码器
        AVCodecParameters *codecpar = format_ctx->streams[audio_stream_index]->codecpar;
        const AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
        if (!codec) {
            avformat_close_input(&format_ctx);
            throw std::runtime_error("找不到合适的解码器");
        }

        codec_ctx = avcodec_alloc_context3(codec);
        if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) {
            avformat_close_input(&format_ctx);
            avcodec_free_context(&codec_ctx);
            throw std::runtime_error("无法设置解码器上下文");
        }

        if (avcodec_open2(codec_ctx, codec, nullptr) < 0) {
            avformat_close_input(&format_ctx);
            avcodec_free_context(&codec_ctx);
            throw std::runtime_error("无法打开解码器");
        }

        // 使用动态声道布局处理
        SwrContext *swr_ctx = nullptr;
        swr_alloc_set_opts2(&swr_ctx,
                            &codec_ctx->ch_layout,  // 保持原始输出声道布局
                            AV_SAMPLE_FMT_FLT,      // 输出格式：float32
                            codec_ctx->sample_rate, // 输出采样率
                            &codec_ctx->ch_layout,  // 输入声道布局
                            codec_ctx->sample_fmt,  // 输入格式
                            codec_ctx->sample_rate, // 输入采样率
                            0, nullptr);

        if (!swr_ctx || swr_init(swr_ctx) < 0) {
            avformat_close_input(&format_ctx);
            avcodec_free_context(&codec_ctx);
            if (swr_ctx)
                swr_free(&swr_ctx);
            throw std::runtime_error("无法初始化重采样器");
        }

        out_sample_rate = codec_ctx->sample_rate;

        AVPacket *packet = av_packet_alloc();
        AVFrame *frame = av_frame_alloc();
        uint8_t *output_data = nullptr;
        int linesize = 0;

        // 主解码循环
        while (av_read_frame(format_ctx, packet) >= 0) {
            if (packet->stream_index == audio_stream_index) {
                int ret = avcodec_send_packet(codec_ctx, packet);
                if (ret < 0 && ret != AVERROR(EAGAIN)) {
                    av_packet_unref(packet);
                    continue;
                }

                while (true) {
                    ret = avcodec_receive_frame(codec_ctx, frame);
                    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
                        break;
                    if (ret < 0)
                        break;

                    // 计算输出样本数
                    int out_samples = av_rescale_rnd(swr_get_delay(swr_ctx, frame->sample_rate) + frame->nb_samples,
                                                     codec_ctx->sample_rate, frame->sample_rate, AV_ROUND_UP);

                    if (av_samples_alloc(&output_data, &linesize, frame->ch_layout.nb_channels, out_samples,
                                         AV_SAMPLE_FMT_FLT, 0) >= 0) {
                        out_samples = swr_convert(swr_ctx, &output_data, out_samples, (const uint8_t **)frame->data,
                                                  frame->nb_samples);
                        if (out_samples > 0) {
                            int total_samples = out_samples * frame->ch_layout.nb_channels;
                            float *float_data = (float *)output_data;
                            audio_data.insert(audio_data.end(), float_data, float_data + total_samples);
                        }
                        av_freep(&output_data);
                    }
                    av_frame_unref(frame);
                }
            }
            av_packet_unref(packet);
        }

        // 刷新解码器
        avcodec_send_packet(codec_ctx, nullptr);
        while (avcodec_receive_frame(codec_ctx, frame) >= 0) {
            // 处理剩余帧
            int out_samples = av_rescale_rnd(swr_get_delay(swr_ctx, frame->sample_rate) + frame->nb_samples,
                                             codec_ctx->sample_rate, frame->sample_rate, AV_ROUND_UP);

            if (av_samples_alloc(&output_data, &linesize, frame->ch_layout.nb_channels, out_samples, AV_SAMPLE_FMT_FLT,
                                 0) >= 0) {
                out_samples =
                    swr_convert(swr_ctx, &output_data, out_samples, (const uint8_t **)frame->data, frame->nb_samples);
                if (out_samples > 0) {
                    int total_samples = out_samples * frame->ch_layout.nb_channels;
                    float *float_data = (float *)output_data;
                    audio_data.insert(audio_data.end(), float_data, float_data + total_samples);
                }
                av_freep(&output_data);
            }
            av_frame_unref(frame);
        }

        // 刷新重采样器
        while (true) {
            int out_samples = av_rescale_rnd(swr_get_delay(swr_ctx, codec_ctx->sample_rate), codec_ctx->sample_rate,
                                             codec_ctx->sample_rate, AV_ROUND_UP);
            if (out_samples <= 0)
                break;

            if (av_samples_alloc(&output_data, &linesize, codec_ctx->ch_layout.nb_channels, out_samples,
                                 AV_SAMPLE_FMT_FLT, 0) >= 0) {
                out_samples = swr_convert(swr_ctx, &output_data, out_samples, nullptr, 0);
                if (out_samples > 0) {
                    int total_samples = out_samples * codec_ctx->ch_layout.nb_channels;
                    float *float_data = (float *)output_data;
                    audio_data.insert(audio_data.end(), float_data, float_data + total_samples);
                }
                av_freep(&output_data);
            }
        }

        // 清理资源
        av_packet_free(&packet);
        av_frame_free(&frame);
        swr_free(&swr_ctx);
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);

        return audio_data;
    }
};

#endif // MSLITEVIDEOENHANCE_VIDEO_PROCESSOR_H
